<template>
    <div class="r-datebox">
      <div class="current-date">
        <i class="iconfont icon-xiangzuo" @click="preMonth"></i>
        <span>{{ dateFormat(data.current, 'yyyy年MM月') }}</span>
        <i class="iconfont icon-xiangzuo next" @click="nextMonth"></i>
        <span class="go-today" @click="goToday">今天</span>
      </div>
      <div class="main-box">
        <div class="week">
          <div class="week-item" v-for="(item,index) in data.weeks" :key="index">{{ item.label }}</div>
        </div>
        <div class="date">
          <div class="date-item"
               :class="{pre : index < data.preCount}"
               v-for="(item,index) in data.dates" :key="index"
               @click="dateClick(item,index)">
            <div :class="{'date-item-value':data.dateIndex == index,today:isToday(item)}">
              {{ item.day }}
            </div>
          </div>
        </div>
      </div>
    </div>
  </template>
  <script setup>
  import {defineEmits, defineProps, onBeforeMount, reactive} from 'vue'
   
  const props = defineProps({
    id: ''
  })
  const emit = defineEmits(['change']);
   
  const data = reactive({
    weeks: [
      {label: '日', value: 0},
      {label: '一', value: 1},
      {label: '二', value: 2},
      {label: '三', value: 3},
      {label: '四', value: 4},
      {label: '五', value: 5},
      {label: '六', value: 6},
    ],
    current: new Date(),
    dateIndex: 0,
    preCount: 0,
    dates: []
  })
   
  const goToday = () => {
    data.current = new Date()
    initDate()
  }
   
  /** 判断是否是当前日期 */
  const isToday = ({date}) => {
    let itemDateStr = dateFormat(date, 'YYYY-MM-dd')
    let todayDateStr = dateFormat(Date.now(), 'YYYY-MM-dd')
    return itemDateStr === todayDateStr
  }
   
  /** 日期点击 **/
  const dateClick = (item, index) => {
    data.dateIndex = index;
    emit('change', dateFormat(item.date), item.date)
  }
   
  /** 上一个月 **/
  const preMonth = () => {
    let y = data.current.getFullYear()
    let m = data.current.getMonth()
    if (m == 0) {
      m = 11
      y -= 1
    } else {
      m -= 1
    }
   
    data.current.setFullYear(y)
    data.current.setMonth(m)
   
    initDate()
  }
   
  /** 下一个月 **/
  const nextMonth = () => {
    let y = data.current.getFullYear()
    let m = data.current.getMonth()
    if (m == 11) {
      m = 0
      y += 1
    } else {
      m += 1
    }
   
    data.current.setFullYear(y)
    data.current.setMonth(m)
   
    initDate()
  }
   
  /** 获取上一个月，返回年月 **/
  const getPreYearAndMonth = () => {
    let y = data.current.getFullYear()
    let m = data.current.getMonth()
    if (m == 0) {
      m = 11
      y = y - 1
    } else {
      m = m - 1
    }
   
    return [y, m]
  }
   
  /** 页面加载完成，初始化日期 **/
  const initDate = () => {
    let y = data.current.getFullYear()
    let m = data.current.getMonth()
    getDates(y, m)
  }
   
  /** 渲染日期 **/
  const getDates = (y, m) => {
    let length = getCountByMonth(y, m)
    data.dates = Array.from({length}, (_, i) => ({
      day: i + 1,
      date: new Date(y, m, i + 1)
    }))
   
    //填充最前面的日期格子
    getPreDays(y, m)
  }
   
  /** 填充最前面的日期格子 **/
  const getPreDays = (y, m) => {
    //获取第一天星期几
    let week = getFirstDayWeek(y, m)
    //如果月份第一天不是周天，则需要向前填充日期
    if (week != 0) {
      let list = []
      //获取上月总共天数
      let preMonthCount = getCountByMonth(y, m - 1)
      let end = preMonthCount - week
      let pre = getPreYearAndMonth()
      while (preMonthCount > end) {
        list.unshift({
          day: preMonthCount,
          date: new Date(pre[0], pre[1], preMonthCount)
        })
        preMonthCount--
      }
   
      data.preCount = list.length
      data.dates.unshift(...list)
   
      //获取当前日期所在的索引值
      let d = new Date()
      if (d.getFullYear() == y && d.getMonth() == m) {
        data.dateIndex = d.getDate() + week - 1
      } else {
        data.dateIndex = -1
      }
    }
  }
   
  /** 获取某年某月总共天数 **/
  const getCountByMonth = (y, m) => {
    return new Date(y, m + 1, 0).getDate()
  }
   
  /** 获取某年某月第一天星期几 **/
  const getFirstDayWeek = (y, m) => {
    return new Date(y, m, 1).getDay()
  }
   
  const dateFormat = (date, format) => {
    if (date) {
      date = date instanceof Date ? date : new Date(date);
      let o = {
        "M+": date.getMonth() + 1,                 //月份
        "d+": date.getDate(),                    //日
        "h+": date.getHours(),                   //小时
        "m+": date.getMinutes(),                 //分
        "s+": date.getSeconds(),                 //秒
        "q+": Math.floor((date.getMonth() + 3) / 3), //季度
        "S": date.getMilliseconds()             //毫秒
      };
   
      format = (format || 'yyyy-MM-dd hh:mm:ss').replace(/y+/i, date.getFullYear());
      for (let i in o) format = format.replace(new RegExp('(' + i + ')'), ('0' + o[i]).slice(-2));
      return format;
    }
    return '';
  }
   
  onBeforeMount(() => {
    initDate()
  })
  </script>
  <style scoped lang="less">
  .r-datebox {
    font-size: var(--content-font-size);
    color: #555;
    padding: 10px;
    width: calc(100% - 20px);
   
    .current-date {
      display: flex;
      align-items: center;
      justify-content: center;
      color: var(--word-active-color);
      margin-bottom: 20px;
      position: relative;
   
      i {
        cursor: pointer;
   
        &.next {
          transform: rotate(180deg);
        }
      }
   
      .go-today {
        position: absolute;
        right: 20px;
        cursor: pointer;
      }
    }
   
    .main-box {
      .week {
        display: flex;
        margin-bottom: 10px;
   
        .week-item {
          color: var(--word-active-color);
          width: calc(100% / 7);
          text-align: center;
          font-weight: 700;
        }
      }
   
      .date {
        display: flex;
        flex-wrap: wrap;
   
        .date-item {
          display: flex;
          align-items: center;
          justify-content: center;
          width: calc(100% / 7);
          height: 30px;
          line-height: 30px;
          text-align: center;
          cursor: pointer;
          color: var(--word-active-color);
   
          .date-item-value {
            position: relative;
            width: 30px;
            height: 30px;
            background: var(--border-color-3);
            border-radius: 50%;
            color: #fff;
          }
   
          .today {
            position: relative;
            width: 30px;
            height: 30px;
   
            &:after {
              position: absolute;
              content: 'Today';
              transform: scale(.5);
              color: var(--box-bg-color-2);
              right: 0;
              top: -6px;
              width: 8px;
              height: 8px;
            }
          }
   
          &.pre {
            color: #bdbdbd;
          }
   
          //&:hover, &.active {
          //  background: var(--bg-blue-color);
          //  color: #fff;
          //  border-radius: 8px;
          //}
   
        }
      }
    }
  }
  </style>